home *** CD-ROM | disk | FTP | other *** search
/ Ham Radio 2000 #1 / Ham Radio 2000.iso / ham2000 / hf / dsp / dsp4src / fsk.asm < prev    next >
Encoding:
Assembly Source File  |  1994-04-01  |  13.7 KB  |  511 lines

  1.     page    132,79
  2.     opt    rc
  3.     title    '1200 bit/s FSK modem'
  4.  
  5. ;***************************************************************
  6. ;* FSK.ASM -- Bell 202 1200 bit/s FSK modem               *
  7. ;*                                   *
  8. ;* Radio Amateur 1200 bit/s FSK modem. Demodulator is based    *
  9. ;* on first-order complex DPLL. Symbol synchro is based on     *
  10. ;* ML symbol synchro.                           *
  11. ;*                                   *
  12. ;* DPLL consepts are from the book:                   *
  13. ;*    Lee, E., A., Messerschmitt, D., G.:               *
  14. ;*    "Digital Communication",                   *
  15. ;*    Kluwer, 1990                           *
  16. ;*                                   *
  17. ;* Sinewave synthesis is from the application note:           *
  18. ;*    Chrysafis, A.:                           *
  19. ;*    "Digital Sine-Wave Synthesis Using the DSP56001",      *
  20. ;*    Motorola application note APR1, 1988               *
  21. ;*                                   *
  22. ;* Symbol synchro is from the article:                   *
  23. ;*    Franks, L., E.:                        *
  24. ;*    "Carrier and bit Synchronization in Data               *
  25. ;*    Communication - A Tutorial Review",                    *
  26. ;*    IEEE Trans. on Communications,                   *
  27. ;*    Vol. COM-28, No. 8, May 1980, p. 1107-1121           *
  28. ;*                                   *
  29. ;* Copyright (C) 1994 by Alef Null. All rights reserved.       *
  30. ;* Author(s): Jarkko Vuori, OH2LNS                   *
  31. ;* Modification(s):                           *
  32. ;***************************************************************
  33.  
  34. kiss    set    1                    ; give KISS data/debug data for SPY
  35.  
  36.     nolist
  37.     include 'leonid'                ; DSP CARD 4 monitor equates
  38.     list
  39.  
  40. sinep    equ    $0100                    ; ROM sine table starting address
  41. sinel    equ    256                    ; lenght of sine table
  42. buflen    equ    256
  43.  
  44. fs    equ    9600                    ; sampling frequency
  45. fd    equ    1200                    ; decision rate
  46. N    equ    fs/fd                    ; samples per symbol
  47. f0    equ    1200.0                    ; low FSK frequency
  48. f1    equ    2200.0                    ; high FSK frequency
  49.  
  50. ; AGC
  51. refLev    equ    0.7                    ; reference level for AGC
  52. agcN    equ    4*N                    ; agc analyse block lenght
  53. agcGain equ    30.0                    ; agc integrator gain
  54.  
  55. ; DPLL
  56. Kg    equ    700.0                    ; NCO gain (in V/Hz)
  57. Kpll    equ    (Kg/fs)/refLev
  58. fc    equ    ((f0+f1)/2)/fs                ; center frequency
  59.  
  60. ; Symbol synchro
  61. Ksym    equ    0.06                    ; symbol synchro pll loop gain
  62.  
  63. ; DCD
  64. DCDFil    equ    0.03                    ; decision error IIR LPF coefficient
  65.  
  66. ; flags
  67. xmit    equ    0                    ; xmit on/off
  68. mkdsion equ    1                    ; time to make a decision
  69. car    equ    2                    ; carrier on/off
  70. spyflg    equ    3                    ; spy on/off
  71.  
  72.  
  73.     org    p:user_code
  74.  
  75.  
  76.     ori    #$04,omr                ; enable on-chip sine table
  77.  
  78.     move            #buffer+2,r7        ; codec sample buffer ptr
  79.     move            #buflen*4-1,m7
  80.  
  81.     move            #buffer+4*16+1,r5        ; sample buffer write ptr
  82.     move            #4,n5
  83.     move            #buflen*4-1,m5
  84.  
  85.     move            #buffer,r2            ; sample buffer read ptr
  86.     move            #4,n2
  87.     move            #buflen*4-1,m2
  88.  
  89.     move            #<dfd,r6            ; decision filter sample ptr
  90.     move            #2,n6
  91.     move            #<dftaps-1,m6
  92.  
  93.     if kiss
  94.     move    #reject,a1                ; serial interface to KISS mode
  95.     move    #ptt,b1
  96.     opensc
  97.     endif
  98.  
  99. ; fs = 9600 kHz, line input, line output, no gain and attenuation
  100.     ctrlcd    1,r2,buflen,LINEI,0.0,0.0,LINEO,0.0,0.0
  101.     opencd    fs/1000.0
  102.  
  103. ; wait for one sample
  104. loop    waitblk r2,buflen,1
  105.  
  106. ; first get next sample from local oscillator
  107.     move            x:<nco,x0            ; frequency in x0
  108.  
  109. ; calculate frequency increment, Finc = sinel*(K*nco + fc)
  110.     move            #Kpll,x1
  111.     move            #fc,a
  112.     macr    x0,x1,a     #>sinel,x0
  113.     move    a,x1
  114.     mpy    x0,x1,a
  115.     move            a10,l:<frqinc1        ; frequency increment is real number
  116.  
  117. ; generate one sinewave sample (Q)
  118.     move            #sinep,r0            ; setup sine table pointers
  119.     move            #sinep+1,r1
  120.     move            x:<frqptr1,n0
  121.     clr    b        n0,n1
  122.     move            #sinel-1,m0
  123.     move            m0,m1
  124.     move            y:<frqptr1,b1        ; convert frqinc1 fraction to signed
  125.     lsr    b        y:(r0+n0),x0
  126.     move    b,x1        y:(r1+n1),b
  127.  
  128.     sub    x0,b        l:<frqptr1,y        ; calculate difference of adjacent sine table entries
  129.     move    b,x0        y:(r0+n0),b
  130.     macr    x0,x1,b     l:<frqinc1,a        ; interpolate output sample
  131.     add    y,a        #>$ff,x0            ; increment table pointer
  132.     and    x0,a        #sinep+sinel/4,r0
  133.     move            a,l:<frqptr1
  134.  
  135. ; generate one cosinewave sample (I)
  136.     move            #sinep+sinel/4+1,r1     ; setup table pointers
  137.     move            y:(r0+n0),x0
  138.     move            y:(r1+n1),a
  139.  
  140.     sub    x0,a                    ; calculate difference of adjacent sine table entries
  141.     move    a,x0        y:(r0+n0),a
  142.     macr    x0,x1,a                 ; interpolate output sample
  143.  
  144. ; output samples (I=a, Q=b)
  145.     move    a,x1
  146.     move    b,y1
  147.  
  148. ; then filter input samples and produce the I channel signal
  149.     move            #buflen*4-1,m0
  150.     move            #-4,n0
  151.     move            #<ifc,r4
  152.  
  153.     move            r2,r0
  154.     clr    a
  155.     move            x:(r0)+n0,x0  y:(r4)+,y0
  156.     rep    #iftaps-1
  157.     mac    x0,y0,a     x:(r0)+n0,x0  y:(r4)+,y0
  158.     macr    x0,y0,a     #qfc,r4
  159.  
  160. ; AGC
  161.     move    a,x0
  162.     move            y:<agc,y0
  163.     mpy    x0,y0,a
  164.     rep    #8
  165.     asl    a
  166.  
  167. ; then filter input samples and produce the Q channel signal
  168.     move            r2,r0
  169.     clr    b
  170.     move            x:(r0)+n0,x0  y:(r4)+,y0
  171.     rep    #iftaps-1
  172.     mac    x0,y0,b     x:(r0)+n0,x0  y:(r4)+,y0
  173.     macr    x0,y0,b     (r2)+n2
  174.  
  175. ; AGC
  176.     move    b,x0
  177.     move            y:<agc,y0
  178.     mpy    x0,y0,b
  179.     rep    #8
  180.     asl    b
  181.  
  182. ; output samples (I=a, Q=b)
  183.     move    a,x0
  184.     move    b,y0
  185.  
  186. ; calculate the phase error, Im{rx*conj(osc)}
  187.     mpy    y0,x1,b
  188.     macr    -x0,y1,b
  189.     move            b,x:<nco            ; this is control to the local NCO
  190.     move            b,y:-(r6)            ; and also input signal for the decision filter
  191.  
  192. ; AGC control
  193.     move    x0,a                    ; find maximum
  194.     abs    a
  195.     move            y:<agcmax,x0
  196.     cmp    x0,a        #>1,x1
  197.     tlo    x0,a
  198.     move            a,y:<agcmax
  199.  
  200.     move            y:<agcn,a            ; if one block searched
  201.     sub    x1,a        #>agcN,x1
  202.     move            a,y:<agcn
  203.     jne    <_agc
  204.  
  205.     move            x1,y:<agcn            ; calculate error and filter it
  206.     clr    b        y:<agcmax,a
  207.     move            b,y:<agcmax
  208.     move            #refLev,b
  209.  
  210.     sub    a,b        #>@pow(2,-5)*agcGain/(fs/agcN),x1  ; rectangular integration
  211.     move    b,x0
  212.     move            y:<agc,a
  213.     macr    x0,x1,a
  214.     move            a,y:<agc
  215. _agc
  216.  
  217. ; Generate the output signal
  218.     move            #sinep,r0            ; setup sine table pointers
  219.     move            #sinep+1,r1
  220.     move            x:<frqptr2,n0
  221.     clr    b        n0,n1
  222.     move            #sinel-1,m0
  223.     move            m0,m1
  224.     move            y:<frqptr2,b1        ; convert frqinc fraction to signed
  225.     lsr    b        y:(r0+n0),x0
  226.     move    b,x1        y:(r1+n1),b
  227.  
  228.     sub    x0,b        l:<frqptr2,y        ; calculate difference of adjacent sine table entries
  229.     move    b,x0        y:(r0+n0),b
  230.     macr    x0,x1,b     l:<frqinc2,a        ; interpolate output sample
  231.     add    y,a        #>$ff,x0            ; increment table pointer
  232.     and    x0,a        #0.7,y1            ; output generated sample
  233.     move    b,y0
  234.     mpyr    y0,y1,a     a,l:<frqptr2
  235.     jset    #xmit,x:<flag,_out1            ; if xmit on, then output signal
  236.     move            p:(r7),a            ; else give noise on output
  237.     asr    a
  238. _out1    move            a,y:(r5)+n5
  239.  
  240. ; Get next bit to be sent
  241.     move            x:<n,a            ; check if new bit needed
  242.     move            #>1,x0
  243.     sub    x0,a        #>N,x0
  244.     move            a1,x:<n
  245.     jne    <ss0
  246.  
  247.     move            x0,x:<n            ; yes, try to fetch a new one
  248.     if kiss
  249.     getbit
  250.     jne    <_gb1
  251.     andi    #$fe,ccr                ; send zero if no data to be sent
  252.     endif
  253.  
  254. _gb1    rol    a        y:<prvxsym,x0        ; NRZ-S coding
  255.     not    a        #>sinel,x1
  256.     eor    x0,a        #f0/fs,x0
  257.     ror    a        a1,y:<prvxsym
  258.  
  259.     jcc    <_gb2                    ; calculate output frq
  260.     move            #f1/fs,x0
  261. _gb2    mpy    x0,x1,a
  262.     move            a10,l:<frqinc2
  263.  
  264. ; Symbol synchro
  265. ss0    move            y:(r6),a            ; comb filter to remove harmonics
  266.     move            y:(r6+n6),y0
  267.     add    y0,a
  268.     asr    a
  269.     abs    a                    ; get absolute value to generate line at symbol frequence
  270.     move    a,y0
  271.  
  272.     asr    a        x:<clocka,b         ; remove DC with IIR LPF
  273.     asr    b        #sinep,r0            ; and setup sine table pointers
  274.     add    a,b        y0,a
  275.     move            b,x:<clocka
  276.     sub    b,a        #sinep+1,r1
  277.     move            a,x:<clocke
  278.  
  279.     move            x:<frqptr3,n0        ; setup nco
  280.     clr    b        n0,n1
  281.     move            #sinel-1,m0
  282.     move            m0,m1
  283.     move            y:<frqptr3,b1        ; convert frqinc fraction to signed
  284.     lsr    b        y:(r0+n0),x0
  285.     move    b,x1        y:(r1+n1),b
  286.  
  287.     sub    x0,b        l:<frqptr3,y        ; calculate difference of adjacent sine table entries
  288.     move    b,x0        y:(r0+n0),b
  289.     macr    x0,x1,b     l:<frqinc3,a        ; interpolate output sample
  290.     add    y,a        #>$100,x0            ; increment table pointer
  291.     cmp    x0,a        #>$ff,x0            ; if over 2PI then make a decision
  292.     jlo    <ss1
  293.     bset    #mkdsion,x:<flag
  294. ss1    and    x0,a                    ; output generated sample
  295.     move            a,l:<frqptr3
  296.  
  297.     move            x:<clocke,y0        ; multiply local clock with derived signal
  298.     move    b,y1
  299.     mpyr    y0,y1,b     #-Ksym,y0
  300.     move    b,y1
  301.     mpyr    y0,y1,b     #f0/fs,y0
  302.  
  303.     add    y0,b        #>sinel,y0            ; and calculate the symbol clock frq
  304.     move    b,y1
  305.     mpy    y0,y1,b
  306.     move            b10,l:<frqinc3
  307.  
  308. ; Decision filter
  309.     bclr    #mkdsion,x:<flag            ; check if time to make a decision
  310.     jcc    <loop
  311.  
  312.     move            #<dfc,r0            ; yes, first filter the signal from DPLL
  313.     nop
  314.     clr    a        x:(r0)+,x0    y:(r6)+,y0
  315.     rep    #dftaps-1
  316.     mac    x0,y0,a     x:(r0)+,x0    y:(r6)+,y0
  317.     macr    x0,y0,a
  318.  
  319. ; make symbol decision (with NRZ-S decoding)
  320.     move            y:<prvrsym,x0
  321.     eor    x0,a        a1,y:<prvrsym
  322.     not    a
  323.     btst    #23,a1
  324.  
  325. ; forward to the HDLC handler
  326.     if kiss
  327.     putbit
  328.     endif
  329.  
  330. ; calculate decision error
  331.     move            y:<prvrsym,b
  332.     abs    b        #((f1-f0)/2)/Kg,x0
  333.     sub    x0,b
  334.     abs    b        #DCDFil,x1
  335.  
  336. ; filter it (with first order IIR filter)
  337.     move    b,x0
  338.     mpy    x0,x1,b     #(1.0-DCDFil),x0
  339.     move            y:<decierr,x1
  340.     macr    x0,x1,b
  341.     move            b,y:<decierr
  342.  
  343. ; and make decision if carrier detected
  344.     jset    #car,x:<flag,_caron
  345.     move            #0.75/3-0.02,x0        ; check if carrier appeared
  346.     cmp    x0,b
  347.     jgt    _car2
  348.     bset    #2,x:$FFE4
  349.     bset    #car,x:<flag
  350.     caron
  351.     jmp    <_car2
  352.  
  353. _caron    move            #0.75/3+0.2,x0        ; check if carrier disappeared
  354.     cmp    x0,b
  355.     jlt    _car2
  356.     bclr    #2,x:$FFE4
  357.     bclr    #car,x:<flag
  358.     caroff
  359. _car2
  360.  
  361. ; loop forever
  362.     jmp    <loop
  363.  
  364.  
  365. ; KISS parameter handling
  366. reject    rts
  367.  
  368. ; transmitter PTT control
  369. ptt    jcc    _pttoff
  370.     bset    #0,x:$FFE4
  371.     bset    #xmit,x:<flag
  372.     rts
  373. _pttoff bclr    #0,x:$FFE4
  374.     bclr    #xmit,x:<flag
  375.     rts
  376.  
  377.  
  378. ; *** DEBUG ***
  379. ; special spy
  380. spy    jset    #spyflg,x:<flag,_spyon
  381.  
  382.     lookc                        ; check if spy operation requested
  383.     jcs    <_spyend
  384.     move            #>'S',a
  385.     cmp    x0,a
  386.     jne    <_spyend
  387.  
  388.     move            #>'P',x0            ; yes, send first a preamble
  389.     putc
  390.     move            #>512,a1
  391.     move            a1,x:<spyn
  392.     move            #>1,a1
  393.     move            a1,x:<spym
  394.     bset    #spyflg,x:<flag
  395.     jmp    <_spyend
  396.  
  397. ; spy is active, send a register to the host
  398. _spyon    move            x:<spym,b
  399.     move            #>1,y1
  400.     sub    y1,b        #>1,y1
  401.     move            b,x:<spym
  402.     jne    <_spyend
  403.     move            y1,x:<spym
  404.  
  405.     move            a,y0            ; LSB first
  406.     rep    #8
  407.     lsr    a
  408.     move    a1,x0
  409.     putc
  410.  
  411.     move            y0,a            ; then HSB
  412.     rep    #16
  413.     lsr    a
  414.     move    a1,x0
  415.     putc
  416.  
  417.     move            x:<spyn,a            ; check if all samples allready given
  418.     move            #>1,x0
  419.     sub    x0,a
  420.     move            a,x:<spyn
  421.     jne    <_spyend
  422.     bclr    #spyflg,x:<flag
  423.  
  424. _spyend rts
  425.  
  426.  
  427.     org    l:user_data
  428.  
  429. frqinc1 ds    1                    ; demodulator DPLL synthesizer
  430. frqptr1 dc    0
  431.  
  432. frqinc2 dc    256*2200.0/fs*@pow(2,-23)        ; output wave synthesizer
  433. frqptr2 dc    0
  434.  
  435. frqinc3 dc    256*1200.0/fs*@pow(2,-23)        ; symbol clock synthesizer
  436. frqptr3 dc    0
  437.  
  438. buffer    dsm    buflen*4
  439.  
  440.  
  441.     org    x:user_data+6
  442.  
  443. flag    dc    0
  444.  
  445. nco    dc    0
  446.  
  447. n    dc    N
  448.  
  449. clocka    dc    0
  450. clockb    dc    0
  451. clocke    ds    1
  452.  
  453. spyn    ds    1
  454. spym    ds    1
  455. apux    ds    1
  456.  
  457.  
  458. ; Decision filter
  459. dfc    dc    -0.00041567696103898691,-0.00081890562387841972,-0.00077287490021642181,1.2127626692456339E-18,0.0012649095635366239
  460.     dc    0.0022206573645156612,0.0019203394725415372,-2.4103681676650389E-18,-0.0027727292080740626,-0.0046459993765459286
  461.     dc    -0.0038631268777868074,3.908467500183978E-18,0.0052444495308750288,0.008578347763639995,0.0069893345319871946
  462.     dc    -5.5625867930785253E-18,-0.009204649706698589,-0.014902880347551255,-0.012059755791003872,7.1756438651449731E-18
  463.     dc    0.015845903566402978,0.02579978381752315,0.02111502337770264,-8.5315994303790973E-18,-0.029056447470843367
  464.     dc    -0.049268154359086921,-0.042777427656427156,9.4358452693819397E-18,0.073704602333730412,0.15797540308255884
  465.     dc    0.22479821342437376,0.25020332089952807,0.22479821342437376,0.15797540308255884,0.073704602333730412
  466.     dc    9.4358452693819397E-18,-0.042777427656427156,-0.049268154359086921,-0.029056447470843367,-8.5315994303790973E-18
  467.     dc    0.02111502337770264,0.02579978381752315,0.015845903566402978,7.1756438651449731E-18,-0.012059755791003872
  468.     dc    -0.014902880347551255,-0.009204649706698589,-5.5625867930785253E-18,0.0069893345319871946,0.008578347763639995
  469.     dc    0.0052444495308750288,3.908467500183978E-18,-0.0038631268777868074,-0.0046459993765459286,-0.0027727292080740626
  470.     dc    -2.4103681676650389E-18,0.0019203394725415372,0.0022206573645156612,0.0012649095635366239,1.2127626692456339E-18
  471.     dc    -0.00077287490021642181,-0.00081890562387841972,-0.00041567696103898691
  472. dftaps    equ    *-dfc
  473.  
  474.  
  475.     org    y:user_data+6
  476.  
  477. agc    dc    @pow(2,-7)
  478. agcn    dc    agcN
  479. agcmax    dc    0
  480.  
  481. decierr dc    0
  482.  
  483. prvxsym ds    1
  484. prvrsym ds    1
  485.  
  486. dfd    dsm    dftaps
  487.  
  488. ; Bandpass filter (I)
  489. ifc    dc    -2.6158392e-03,-9.0552363e-04,-7.8803034e-19,-3.3417659e-03,-3.9437887e-03
  490.     dc    5.8712929e-03,1.1637071e-02,2.1618050e-03,5.6086809e-03,3.1781607e-02
  491.     dc    2.4681104e-02,-2.6383625e-02,-3.1286527e-02,1.0386163e-02,-5.0248521e-02
  492.     dc    -1.9543656e-01,-1.4305906e-01,1.7572822e-01,3.7525749e-01,1.7572822e-01
  493.     dc    -1.4305906e-01,-1.9543656e-01,-5.0248521e-02,1.0386163e-02,-3.1286527e-02
  494.     dc    -2.6383625e-02,2.4681104e-02,3.1781607e-02,5.6086809e-03,2.1618050e-03
  495.     dc    1.1637071e-02,5.8712929e-03,-3.9437887e-03,-3.3417659e-03,-7.8803034e-19
  496.     dc    -9.0552363e-04,-2.6158392e-03
  497. iftaps    equ    *-ifc
  498.  
  499. ; Bandpass filter (Q)
  500. qfc    dc    -0.0000000e+00,-1.5684129e-03,1.3649086e-18,4.0924827e-19,-6.8308425e-03
  501.     dc    -1.0169378e-02,-2.8502602e-18,3.7443561e-03,-9.7145203e-03,4.4779103e-17
  502.     dc    4.2748926e-02,4.5697779e-02,1.5325978e-17,1.7989363e-02,8.7032991e-02
  503.     dc    -2.2749469e-16,-2.4778556e-01,-3.0437020e-01,1.0574477e-15,3.0437020e-01
  504.     dc    2.4778556e-01,-5.2679160e-16,-8.7032991e-02,-1.7989363e-02,3.0651955e-17
  505.     dc     -4.5697779e-02,-4.2748926e-02,7.7881830e-17,9.7145203e-03,-3.7443561e-03
  506.     dc    2.7091879e-17,1.0169378e-02,6.8308425e-03,-7.3706064e-18,-1.3649086e-18
  507.     dc    1.5684129e-03,3.8441750e-18
  508.  
  509.  
  510.     end
  511.